package io.renren.common.utils;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSignerUtil;
import io.renren.common.model.TokenInfo;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;

@Slf4j
public class WebUtil {
    /**
     * 密钥
     */
    public static final String SECRET = "6eea9b7ef19179a06954edd0f6c05ceb";
    /**
     * token过期时间24小时
     */
    public static final int EXPIRATION = 24;
    /**
     * token请求头key
     */
    public static final String TOKEN_KEY = "token";

    /**
     * 获取request
     */
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }

    /**
     * 从request中获取token，兼容header和参数两种方式
     */
    public static String getTokenFromRequest(HttpServletRequest request) {
        String token = request.getHeader(TOKEN_KEY);
        if (StrUtil.isEmpty(token)) {
            token = request.getParameter(TOKEN_KEY);
        }

        if (StrUtil.isEmpty(token)) {
            String authorization = request.getHeader("Authorization");
            if (StrUtil.isNotEmpty(authorization) && authorization.startsWith("Bearer ")) {
                token = authorization.substring(7);
            }
        }

        return JWTUtil.verify(token, SECRET.getBytes()) ? token : null;
    }

    /**
     * 生成token
     */
    public static TokenInfo createToken(long userId) {
        DateTime expiresAt = DateTime.now().offset(DateField.HOUR_OF_DAY, EXPIRATION);
        String token = JWT.create().setSubject(String.valueOf(userId)).setIssuedAt(new Date()).setExpiresAt(expiresAt.toJdkDate()).setSigner(JWTSignerUtil.hs512(SECRET.getBytes())).sign();
        return TokenInfo.builder().expiresAt(expiresAt.getTime()).tokenValue(token).loginId(String.valueOf(userId)).build();
    }

    /**
     * 校验token是否过期
     */
    public static boolean isTokenExpired(String token) {
        try {
            JWTValidator.of(token).validateDate(DateUtil.date());
        } catch (ValidateException e) {
            return false;
        }
        return true;
    }

    public static SysUserEntity getLoginUser() {
        SysUserService sysUserService = SpringUtil.getBean(SysUserService.class);

        return sysUserService.getById(getLoginUserId());
    }

    public static final String LOGIN_USERID_KEY = "__LOGIN_USER_ID__";

    /**
     * 获取当前登录用户ID
     */
    public static Long getLoginUserId() {
        HttpServletRequest request = getHttpServletRequest();
        Object userId = request.getAttribute(LOGIN_USERID_KEY);
        if (userId != null) {
            return Long.valueOf(userId.toString());
        }
        return StpUtil.getLoginIdAsLong();
    }

    public static boolean isSuperAdmin() {
        return Objects.equals(getLoginUserId().intValue(), Constant.SUPER_ADMIN);
    }

    public static void setLoginUserId(Long userId) {
        HttpServletRequest request = getHttpServletRequest();
        request.setAttribute(LOGIN_USERID_KEY, userId);
    }

    public static String getIpAddress() {
        return getIpAddress(getHttpServletRequest());
    }

    /**
     * 获取IP地址
     * <p>
     * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            log.error("getIpAddress ERROR ", e);
        }

        //使用代理，则获取第一个IP地址
        if (ip != null && ip.indexOf(",") > 0) {//ipv6怎么说？
            ip = ip.substring(0, ip.indexOf(","));
        }
        return ip;
    }
}
